#include <iostream>
#include <rapidjson/document.h>


int main(int argc, char* argv[])
{
    // std::string json_str = "[0,1,2,3,4]"; // parse failed
    // std::string json_str = "{[0,1,2,3,4]}"; // parse failed
    // std::string json_str = "{\"number\": [0,1,2,3,4]}"; // parse successfully
    std::string json_str = "{\"name\":\"张三\",\"number\":[0,1,2,3,4]}";
    rapidjson::Document json_doc;
    json_doc.Parse<0>(json_str.c_str());
    if (json_doc.IsObject()) {
        std::cout << "rapidjson | parse " << json_str << " successfully." << std::endl;
    } else {
        std::cout << "rapidjson | parse " << json_str << " failed." << std::endl;
        return -1;
    }

    auto iter = json_doc.MemberBegin();
    for (; iter != json_doc.MemberEnd(); ++iter) {
        rapidjson::Value key, value;
        rapidjson::Document::AllocatorType  allocator;
        key.CopyFrom(iter->name, allocator);
        value.CopyFrom(iter->value, allocator);

        if (key.IsString()) {
            std::cout << "key is string, key: " << key.GetString() << std::endl;
        }

        if (value.IsString()) {
            std::cout << "value is string, value: " << value.GetString() << std::endl;
        } else if(value.IsArray()) {
            std::cout << "value is array" << std::endl;
        }
    }

    if (json_doc.HasMember("name")) {
        std::cout << "has member name" << std::endl;
        auto& name_value = json_doc["name"];
        if (name_value.IsString()) {
            std::cout << "name is string" << std::endl;
            std::cout << name_value.GetString() << std::endl;
        } else {
            std::cout << "name is not string" << std::endl;
        }
    } else {
        std::cout << "does not has member name" << std::endl;
    }

    if (json_doc.HasMember("number")) {
        std::cout << "has member number" << std::endl;
        auto& num_value = json_doc["number"];
        if (num_value.IsString()) {
            std::cout << "num is string" << std::endl;
        } else if (num_value.IsInt()) {
            std::cout << "num is integer" << std::endl;
        } else if (num_value.IsArray()) {
            std::cout << "num is array" << std::endl;
            for (size_t i=0; i<num_value.Size(); ++i) {
                std::cout << "number[" << i << "] is " << num_value[i].GetInt() << std::endl;
            }
        }

        if (num_value.IsObject()) {
            std::cout << "num is also object" << std::endl;
        } else {
            std::cout << "num is array but not object" << std::endl;
        }
    }

    return 0;
}